/*
 * Copyright 2019-2029 geekidea(https://github.com/geekidea)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.chaochis.springboottestdemo.config.reqResConfig;

import com.alibaba.fastjson.JSON;
import com.chaochis.springboottestdemo.base.ApiResult;
import com.chaochis.springboottestdemo.config.corsConfig.CorsProperties;
import com.chaochis.springboottestdemo.config.reqResConfig.dispatcherConfig.CustomRequestWrapper;
import com.chaochis.springboottestdemo.model.commonModel.RequestInfo;
import com.chaochis.springboottestdemo.model.commonModel.ResponseInfo;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.fusesource.jansi.Ansi;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.util.*;

/**
 * <p>
 * Controller Aop
 * 获取响应结果信息
 * </p>
 *
 * @author geekidea
 * @date 2019-10-23
 */
@Slf4j
@Aspect
@Component
public class ControllerAop {

  @Qualifier("corsProperties")
  private final CorsProperties corsProperties;


  @Data
  private static class AopRequestInfo {
    private RequestInfo requestInfo;
    private Boolean hasRequestBodyAnnotation;
    private Object requestFrontBodyParams;
  }
  /**
   * 切点
   */
  private static final String POINTCUT = "execution(public * com.chaochis.*.controller..*.*(..))";

  public ControllerAop(CorsProperties corsProperties) {
    this.corsProperties = corsProperties;
  }

  @Around(POINTCUT)
  public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    return this.handle(joinPoint);
  }

  public Object handle(ProceedingJoinPoint joinPoint) throws Throwable {
    // 获取请求相关信息
    try {
      var httpServletRequest = new CustomRequestWrapper(((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(), this.corsProperties);
      var requestInfo = new AopRequestInfo();
      requestInfo.setRequestInfo(httpServletRequest.getRequestInfo());
      var signature = joinPoint.getSignature();
      var method = ((MethodSignature)signature).getMethod();
      requestInfo.setHasRequestBodyAnnotation(isRequestBody(method.getParameterAnnotations()));
      requestInfo.setRequestFrontBodyParams(getRequestFrontBodyParamsArray(httpServletRequest));
      var requestJsonInfo = JSON.toJSONString(requestInfo, true);
      var ansiText = Ansi.ansi().eraseScreen().fg(Ansi.Color.BLUE).a("requestInfo:" + requestJsonInfo).reset().toString();
      System.out.println(ansiText);
    } catch (Exception e) {
      e.printStackTrace();
    }
    Object result = joinPoint.proceed();

    try{
      if(result instanceof ApiResult) {
        var responseInfo = new ResponseInfo();
        responseInfo.setResponseParams(result);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    // 执行目标方法,获得返回值
    return result;
  }

  private boolean isRequestBody(Annotation[][] annotations) {
    boolean isRequestBody = false;
    for (var annotationArray : annotations) {
      for (var annotation : annotationArray) {
        if (annotation instanceof RequestBody) {
          isRequestBody = true;
          break;
        }
      }
    }
    return isRequestBody;
  }

  /**
   * 获取前端传过来的在body的参数
   * @param request
   * @return
   */
  protected Map<String, Object> getRequestFrontBodyParamsArray(HttpServletRequest request) {
    var params = new HashMap<String, Object>();
    // TODO: 2021/1/29
    return params;
  }



  protected List<Object> getRequestBackgroundParamsArray(ProceedingJoinPoint pointcut) {
    var params = new ArrayList<Object>();
    var args = pointcut.getArgs();
    if(args == null || args.length == 0) {
      return null;
    }
    for(var object : args) {
      if(object == null || object instanceof HttpServletRequest || object instanceof HttpServletResponse || object instanceof MultipartFile) {
        continue;
      }
      params.add(object);
    }
    return params;
  }

}
